package top.yangbuyi.config;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

/**
 * @program: coinex-change
 * @ClassName: AuthorizationServerConfig
 * @create: 2021-01-01 20:47
 * @author: yangshuai
 * @since： JDK1.8
 * @AuthorizationServerConfig: 开启授权管理器$
 **/
@SuppressWarnings({"ALL", "AlibabaRemoveCommentedCode"})
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	@Qualifier("userServiceDetailsServiceImpl")
	private UserDetailsService userDetailsService;

	/**
	 * @功能描述:redis连接工厂
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/1 21:34
	 */


	/**
	 * @功能描述:添加第三方的客户端
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/1 20:48
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		// 访问oauth/token/  需要进行输入客户端名称与密钥
		clients.inMemory() // 存放在内存当中
				.withClient("coin-api") // 第三方客户端名称
				.secret(passwordEncoder.encode("coin-secret")) // 第三方客户端的密钥
				.scopes("all") // 第三方客户端的授权范围
				.accessTokenValiditySeconds(3600) // token 的有效期
				.authorizedGrantTypes("password", "refresh_token") // 刷新token类型为 密码授权刷新
				.refreshTokenValiditySeconds(7 * 3600) // refresh_token的有效期  刷新token的有效期
		;
		super.configure(clients);
	}

	/**
	 * @功能描述:配置验证管理器-UserDetailService
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/1 20:48
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.authenticationManager(authenticationManager) // 验证管理器
				.userDetailsService(userDetailsService) // 自定义用户业务
				.tokenStore(jwtTokenStore()) // 用来存储 token 避免多台验证服务器数据不同步
				.tokenEnhancer(jwtAccessTokenConverter()) // 转换器 登陆的实体转换为json存储jwt
		;
		super.configure(endpoints);
	}


	/**
	 * @功能描述:使用jwt进行存储用户信息
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/1 22:45
	 */
	public TokenStore jwtTokenStore() {
		return new JwtTokenStore(jwtAccessTokenConverter());
	}

	/**
	 * @功能描述:加载私钥文件
	 * @Description:coinexchange私钥解析的口令
	 * @Author: yangshuai
	 * @Date: 2021/1/1 22:50
	 */
	public JwtAccessTokenConverter jwtAccessTokenConverter() {
		JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
		ClassPathResource classPathResource = new ClassPathResource("coinexchange.jks");
		KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, "coinexchange".toCharArray());
		jwtAccessTokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("coinexchange", "coinexchange".toCharArray()));
		return jwtAccessTokenConverter;
	}


	/**
	 * @功能描述:注入redisStore
	 * @Description:
	 * @Author: yangshuai
	 * @Date: 2021/1/1 21:35
	 */
//	public TokenStore redisTokenStore() {
//		return new RedisTokenStore(redisConnectionFactory);
//	}

}
